#include "insn.h"
#include <stdio.h>

#define R1_TO_R2        4
#define R2_TO_R1        1

#define NTT             0
#define INTT            1
#define PWM1            2
#define PWM2            3
#define PolyAdd         4
#define Encode_ADD      5
#define Decode_SUB      6
#define PolyMov         7

#define Compress10      32
#define Compress4       33
#define Compress11      34
#define Compress5       35
#define Compare10       36
#define Compare4        37
#define Compare11       38
#define Compare5        39

#define Decompress10    40
#define Decompress4     41
#define Decompress11    42
#define Decompress5     43


//void kyber512_keygen(void);
void kyber1024_keygen(void);
//void kyber512_enc(void);
void kyber1024_enc(void);
//void kyber512_dec(void);
void kyber1024_dec(void);

void kyber1024_enc_verify(void);
// test case using NICE accelerator.


void Polyshow(volatile unsigned int poly[],char str[], int mode, int num)
{
    printf("%s \r\n",str);
    if(mode == 0)
    {
        for(int i=0; i<num/16;i++ )
        {
            for(int j=0;j<16;j++)
            {
                printf("%d \r\n", poly[16*i+j]);
            }
        }
    }
    else if(mode == 1)
    {
        for(int i=0; i<num/8;i++ )
        {
        	printf(" %x %x %x %x %x %x %x %x \r\n",	poly[8*i+7],poly[8*i+6],poly[8*i+5],poly[8*i+4],
        											poly[8*i+3],poly[8*i+2],poly[8*i+1],poly[8*i+0]);
        }
    }
}

void Seedshow(volatile unsigned int seed[],uint8_t  name[],int length)
{
    printf("%s\n",name);
    for(int i=0;i<length/8;i++)
    {
        printf("%02x%02x%02x%02x \r\n",seed[8*i+3],seed[8*i+2],seed[8*i+1],seed[8*i+0]);
        printf("%02x%02x%02x%02x \r\n",seed[8*i+7],seed[8*i+6],seed[8*i+5],seed[8*i+4]);
    }
}

void nice_case(unsigned int message[])
{
//  volatile unsigned char i, j;
//  volatile unsigned int col_sum[COL_LEN]={0};
//  volatile unsigned int row_sum[ROW_LEN]={0};
//  volatile unsigned int init_buf[3]={0};

	volatile unsigned int seed_d[8] = {0x03020100,0x07060504,
			0x0b0a0908,0x0f0e0d0c,
			0x13121110,0x17161514,
			0x1b1a1918,0x1f1e1d1c,};

	volatile unsigned int m[8] = {0x1d1e1f20,0x191a1b1c,
			0x15161718,0x11121314,
			0x0d0e0f10,0x090a0b0c,
			0x05060708,0x01020304};

	volatile unsigned int rou[8];
	volatile unsigned int k[8];
	volatile unsigned int t[192];
	volatile unsigned int s[192]; //96*32*2
	volatile unsigned int u[192]; //96*32*2
	volatile unsigned int v[96]; //96*32
	volatile unsigned int decode_m[8]; //32*8

	volatile unsigned int t_1024[384];
	volatile unsigned int s_1024[384]; //96*32*4
	volatile unsigned int u_1024[384]; //96*32*4

	unsigned int begin_instret, end_instret, instret_normal, instret_nice;
	unsigned int begin_cycle, end_cycle, cycle_normal, cycle_nice;

//////////////////////////////////////////////Keygen 512////////////////////////////////////////////////////////
//	custom_kyber_load_d((int)seed_d); //加载随机数seed
//	kyber512_keygen();
//	//存储keygen后的随机数ρ，sk，pk
//	custom_kyber_store_rou((int)rou);
//	custom_kyber_store_t_512((int)t);
//	custom_kyber_store_s_512((int)s);
////////////////////////////////////////////////Enc 512////////////////////////////////////////////////////////
//	//Enc 512 加载明文m，ρ，pk
//	custom_kyber_load_m((int)m);      //额外地址8
//	custom_kyber_load_rou((int)rou);  //额外地址9
//	custom_kyber_load_t_512((int)t);	  //地址10
//	kyber512_enc();
//
//	custom_kyber_store_u_512((int)u);
//	custom_kyber_store_v_512((int)v);
////////////////////////////////////////////////Dec 512////////////////////////////////////////////////////////
//
//	custom_kyber_load_u_512((int)u);	//RAM2地址0
//	custom_kyber_load_v_512((int)v);	//RAM2地址2
//	custom_kyber_load_s_512((int)s);  	//RAM1地址8
//	kyber512_dec();
//
//	custom_kyber_store_m((int)decode_m);
//	custom_kyber_load_m((int)decode_m);
//	//SHA3_Enable,6'b000010
//	//rs1=8 rs2=11 dst=11			//G(m|Hpk) K 512bit 000
//	asm volatile (".insn r 0x0b, 0, 0b0000010, x11, x8, x11");

//////////////////////////////////////////////Keygen 1024////////////////////////////////////////////////////////
	custom_kyber_load_d_1024((int)seed_d); //加载随机数seed

	//EXU///////////////////////////////////////////////////////////////
	begin_cycle = __get_rv_cycle();
	kyber1024_keygen();
	end_cycle = __get_rv_cycle();
	cycle_normal = end_cycle - begin_cycle;
	//EXU////////////////////////////////////////////////////////////////
	//存储keygen后的随机数ρ，sk，pk
	custom_kyber_store_rou_1024((int)rou);
	custom_kyber_store_t_1024((int)t_1024);
	custom_kyber_store_s_1024((int)s_1024);

	printf("Keygen cycles: %u\r\n", cycle_normal);
	printf("Keygen Time: %u us\r\n", cycle_normal/360);

//	Polyshow(t_1024,"Public Key", 1, 96);//只看前16组
//	printf("\r\n");
//	Polyshow(s_1024,"Private Key", 1, 96);//只看前16组
//	Seedshow(rou,"rou",8);
//////////////////////////////////////////////Enc 1024////////////////////////////////////////////////////////
	//Enc 1024 加载明文m，ρ，pk
	custom_kyber_load_m((int)m);      //额外地址0
	custom_kyber_load_rou_1024((int)rou);  //额外地址1
	custom_kyber_load_t_1024((int)t_1024);	  //地址4

	begin_cycle = __get_rv_cycle();
	kyber1024_enc();
	end_cycle = __get_rv_cycle();
	cycle_normal = end_cycle - begin_cycle;

	custom_kyber_store_u_1024((int)u_1024);
	custom_kyber_store_v_1024((int)v);
	printf("\r\n");
	printf("Enc cycles: %u\r\n", cycle_normal);
	printf("Enc Time: %u us\r\n", cycle_normal/360);
////////////////////////////////////////////////Dec 1024////////////////////////////////////////////////////////
	custom_kyber_load_u_1024((int)u_1024);	//RAM2地址0
	custom_kyber_load_v_1024((int)v);	//RAM2地址4
	custom_kyber_load_s_1024((int)s_1024);  	//RAM1地址0

	begin_cycle = __get_rv_cycle();
	kyber1024_dec();
	end_cycle = __get_rv_cycle();
	cycle_normal = end_cycle - begin_cycle;

	custom_kyber_store_m((int)decode_m);
	custom_kyber_load_m((int)decode_m);

	begin_cycle = __get_rv_cycle();
	kyber1024_enc_verify();
	end_cycle = __get_rv_cycle();
	cycle_nice = end_cycle - begin_cycle;

	custom_kyber_store_k((int)k);


	Seedshow(k,"Session Key:",8); //显示解密后的封装密钥

	printf("\r\n");
	printf("message:\r\n");
	printf("%x%x%x%x \r\n",m[3],m[2],m[1],m[0]);
	printf("%x%x%x%x \r\n",m[7],m[6],m[5],m[4]);
	printf("\r\n");
	Seedshow(decode_m,"Decode_message:",8); //显示解密后的明文
	printf("\r\n");

	printf("Dec cycles: %u\r\n", cycle_normal+cycle_nice);
	printf("Dec Time: %u us\r\n", (cycle_normal+cycle_nice)/360);
	printf("\r\n");
}


